#pragma once
#include <stdint.h>
#include "Arduino.h"

class Buffer
{
public:
    typedef enum
    {
        LittleEnd,
        BigEnd,
    } DataTyep_t;
    // 定义错误码枚举
    typedef enum
    {
        NO_ERROR,
        INDEX_OUT_OF_RANGE
    } Err_t;
    Buffer();

    ~Buffer();
    void append_u32(uint32_t value, DataTyep_t type = LittleEnd);
    void append_u16(uint16_t value, DataTyep_t type = LittleEnd);
    void append_u8(uint8_t value);
    void append(const uint8_t *data, uint16_t size);
    void append(const char *str);
    void append(const Buffer &other);
    uint32_t to_u32(uint16_t index, DataTyep_t type = LittleEnd);
    uint16_t to_u16(uint16_t index, DataTyep_t type = LittleEnd);
    int32_t to_i32(uint16_t index, DataTyep_t type = LittleEnd);
    int16_t to_i16(uint16_t index, DataTyep_t type = LittleEnd);
    float to_float(uint16_t index, DataTyep_t type = LittleEnd);

    // 自动管理 index 顺序的读取方法
    uint32_t read_u32(DataTyep_t type = LittleEnd);
    uint16_t read_u16(DataTyep_t type = LittleEnd);
    uint8_t read_u8();
    int32_t read_i32(DataTyep_t type = LittleEnd);
    int16_t read_i16(DataTyep_t type = LittleEnd);
    int8_t read_i8();
    float read_float(DataTyep_t type = LittleEnd);
    Buffer read_buf(uint16_t size);
    String read_String();

    // 新增读取字符串的方法声明

    // 新增设置 readIndex 的接口
    void setReadIndex(uint16_t newIndex);
    // 新增获取 readIndex 的接口
    uint16_t getReadIndex() const;

    // 获取错误状态的接口
    Err_t getError() const;

    void clear();
    const uint8_t *data() const;
    uint16_t size() const;

    Buffer operator+(const Buffer &other) const;

    Buffer(const Buffer &other);    // 复制构造函数
    Buffer &operator=(const Buffer &other);    // 复制赋值运算符
    Buffer(Buffer &&other) noexcept;    // 移动构造函数
    Buffer &operator=(Buffer &&other) noexcept;    // 移动赋值运算符
private:
    uint8_t *buf;
    uint16_t length;
    uint16_t capacity;
    uint16_t readIndex; // 记录当前读取位置
    Err_t err;          // 新增：错误状态变量
    void expandCapacity(uint16_t minRequired);
    void setError(Err_t error); // 新增：设置错误状态的私有方法
};